package com.lzs.common.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzs.common.dao.SysMenuDao;
import com.lzs.common.dto.PageQuery;
import com.lzs.common.dto.menu.*;
import com.lzs.common.pojo.common.SysMenu;
import com.lzs.common.pojo.common.bo.SysMenuBo;
import com.lzs.common.service.SysMenuService;
import com.lzs.common.utils.valid.BeanValidator;
import com.lzs.common.utils.valid.NumberValidator;
import com.lzs.common.vo.CommonResult;
import com.lzs.common.vo.SelectVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;


import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuDao, SysMenu> implements SysMenuService {

    @Autowired
    private SysMenuDao sysMenuDao;

    @Override
    public CommonResult<SysMenu> getByPage(PageQuery pageQuery, SysMenuGetByPageDto dto) {
        baseMapper.getByPage(pageQuery.toPage(), dto);
        return pageQuery.toCommonResult();
    }

    @Override
    public CommonResult<SysMenu> getById(String id) {
        SysMenu sysMenu = baseMapper.selectById(id);
        return CommonResult.OK(sysMenu);
    }

    @Override
    public CommonResult updateById(SysMenuUpdateByIdDto dto) {
        BeanValidator.check(dto, SysMenuUpdateByIdDto.class);
        SysMenu sysMenu = new SysMenu();
        BeanUtils.copyProperties(dto, sysMenu);
        int updateRow = baseMapper.updateById(sysMenu);
        NumberValidator.checkIsNotOne(updateRow, "修改失败");
        return CommonResult.OK();
    }

    @Override
    public CommonResult deleteById(String id) {
        int deleteRow = baseMapper.deleteById(id);
        NumberValidator.checkIsNotOne(deleteRow, "删除失败");
        return CommonResult.OK();
    }

    @Override
    public CommonResult deleteFlagById(String id) {
        Integer deleteFlagRow = baseMapper.deleteFlagById(id);
        NumberValidator.checkIsNotOne(deleteFlagRow, "禁用失败");
        return CommonResult.OK();
    }

    @Override
    public CommonResult save(SysMenuSaveDto dto) {
        BeanValidator.check(dto, SysMenuUpdateByIdDto.class);
        SysMenu sysMenu = new SysMenu();
        BeanUtils.copyProperties(dto, sysMenu);
        Integer insertRow = baseMapper.insert(sysMenu);
        NumberValidator.checkIsNotOne(insertRow, "添加失败");
        return CommonResult.OK();
    }

    @Override
    public CommonResult getSysMenuByIdPage(PageQuery pageQuery
            , GetSysMenuByIdPageDto dto) {
        sysMenuDao.selectPage(pageQuery.toPage(), Wrappers.<SysMenu>lambdaQuery()
                .select()
                .eq(SysMenu::getParentId, dto.getParentId())
                .eq(
                        StringUtils.isNotBlank
                                (dto.getId()), SysMenu::getId, dto.getId())

                .like(
                        StringUtils.isNotBlank
                                (dto.getMenuName()), SysMenu::getMenuName, dto.getMenuName())

                .like(
                        StringUtils.isNotBlank
                                (dto.getMenuCode()), SysMenu::getMenuCode, dto.getMenuCode())

                .like(
                        StringUtils.isNotBlank
                                (dto.getVueTitle()), SysMenu::getVueTitle, dto.getVueTitle())

        );
        return pageQuery.toCommonResult();
    }

    @Override
    public CommonResult<SysMenu> getSysMenuById(String id) {
        SysMenu sysMenu = sysMenuDao.selectById(id);
        return CommonResult.OK(sysMenu);
    }

    @Override
    public CommonResult deleteSysMenuById(String id) {
        int deleteRow = sysMenuDao.deleteById(id);
        NumberValidator.checkIsNotOne(deleteRow, "删除失败");
        return CommonResult.OK();
    }

    @Override
    public CommonResult saveSysMenu(SysMenuSaveDto dto) {
        BeanValidator.check(dto, SysMenuUpdateByIdDto.class);
        SysMenu sysMenu = new SysMenu();
        BeanUtils.copyProperties(dto, sysMenu);
        Integer insertRow = sysMenuDao.insert(sysMenu);
        NumberValidator.checkIsNotOne(insertRow, "添加失败");
        return CommonResult.OK();
    }

    @Override
    public CommonResult updateSysMenuById(SysMenuUpdateByIdDto dto) {
        BeanValidator.check(dto, SysMenuUpdateByIdDto.class);
        SysMenu sysMenu = new SysMenu();
        BeanUtils.copyProperties(dto, sysMenu);
        int updateRow = sysMenuDao.updateById(sysMenu);
        NumberValidator.checkIsNotOne(updateRow, "修改失败");
        return CommonResult.OK();
    }

    /**
     * 获取登陆用户的菜单权限
     *
     * @return
     */
    @Override
    public CommonResult getTreeMenuByRoleId(String roleId) {
        List<SysMenu> newSysMenuList = baseMapper.selectParentListByRoleId(roleId);
        this.getTreeMenu(roleId, newSysMenuList);

        return CommonResult.rows(newSysMenuList);
    }

    @Override
    public CommonResult getTreeSelect() {
        //查询第一级
        List<SysMenu> sysMenuList = baseMapper.selectList(Wrappers.<SysMenu>lambdaQuery()
                .select(SysMenu::getId, SysMenu::getMenuName)
                .eq(SysMenu::getParentId, ""));
        List<SelectVo> selectVoList = sysMenuList.stream()
                .map(s -> SelectVo.builder()
                        .label(s.getMenuName())
                        .value(s.getId()).build())
                .collect(Collectors.toList());

        this.getTreeMenuToSelectVo(selectVoList, 1);

        return CommonResult.rows(selectVoList);
    }

    @Override
    public CommonResult getTreeSelectValueByRoleId(String roleId) {
        CommonResult treeMenuByRoleId = this.getTreeMenuByRoleId(roleId);
        List<SysMenu> sysMenuList = treeMenuByRoleId.getRows();
        List<List<String>> menuIdListList = new ArrayList<>();
        for (SysMenu sysMenu : sysMenuList) {
            ArrayList<String> list = new ArrayList<>();
//            menuIdListList.add(list);
            this.getChildrenTreeSelectValueByRoleId(sysMenu, list, menuIdListList);
        }
        return CommonResult.rows(menuIdListList);
    }

    /**
     * 分页查询树状结构
     *
     * @param pageQuery
     * @param dto
     * @return
     */
    @Override
    public CommonResult<SysMenuBo> getListByPage(PageQuery pageQuery, GetThreeByPageDto dto) {
        baseMapper.getListByPage(pageQuery.toPage(),dto);
        CommonResult<SysMenuBo> commonResult = pageQuery.toCommonResult();
        for (SysMenuBo sysMenuBo : commonResult.getRows()) {
            boolean exists = baseMapper.exists(Wrappers.<SysMenu>lambdaQuery()
                    .eq(SysMenu::getParentId, sysMenuBo.getId()));
            sysMenuBo.setHasChildren(exists);
        }
        return commonResult;
    }

    @Override
    public CommonResult<SysMenuBo> getList(GetThreeByPageDto dto) {
        List<SysMenuBo> list = baseMapper.getList(dto);
        for (SysMenuBo sysMenuBo : list) {
            boolean exists = baseMapper.exists(Wrappers.<SysMenu>lambdaQuery()
                    .eq(SysMenu::getParentId, sysMenuBo.getId()));
            sysMenuBo.setHasChildren(exists);
        }
        return CommonResult.rows(list);
    }

    public void getChildrenTreeSelectValueByRoleId(SysMenu sysMenu, ArrayList<String> list, List<List<String>> menuIdListList) {
        list.add(sysMenu.getId());
        List<SysMenu> childList = sysMenu.getChildList();
        if (childList == null || childList.size() == 0) {
            ArrayList<String> menuIdList = new ArrayList<>(list.size());
            for (String s : list) {
                menuIdList.add(s);
            }
            menuIdListList.add(menuIdList);

            Iterator<String> iterator = list.iterator();
            while (iterator.hasNext()) {
                String next = iterator.next();
                if (!iterator.hasNext()) {
                    iterator.remove();
                }
            }

            return;
        }
        for (SysMenu menu : childList) {
            this.getChildrenTreeSelectValueByRoleId(menu, list, menuIdListList);
        }
    }

    public void getTreeMenu(String roleId, List<SysMenu> sysMenuList) {
        for (SysMenu sysMenu : sysMenuList) {
            List<SysMenu> childList = baseMapper.selectByParentId(roleId, sysMenu.getId());
            sysMenu.setChildList(childList);
            if (Objects.isNull(childList) || childList.size() == 0) {
                continue;
            }
            this.getTreeMenu(roleId, childList);
        }
    }

    public void getTreeMenuToSelectVo(List<SelectVo> selectVoList, Integer level) {
        log.info("处理菜单第[{}]级", level);
        for (SelectVo selectVo : selectVoList) {
            List<SysMenu> sysMenuList = baseMapper.selectList(Wrappers.<SysMenu>lambdaQuery()
                    .eq(SysMenu::getParentId, selectVo.getValue()));
            List<SelectVo> childList = sysMenuList.stream().map(s -> SelectVo.builder()
                    .label(s.getMenuName())
                    .value(s.getId()).build()).collect(Collectors.toList());
            if (Objects.isNull(sysMenuList) || sysMenuList.size() == 0) {
                return;
            }
            selectVo.setChildren(childList);
            level++;
            this.getTreeMenuToSelectVo(childList, level);
        }
    }
}
